home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CU Amiga Super CD-ROM 15
/
CU Amiga Magazine's Super CD-ROM 15 (1997)(EMAP Images)(GB)[!][issue 1997-10].iso
/
CUCD
/
Graphics
/
Ghostscript
/
source
/
gp_amiga.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-07-05
|
22KB
|
907 lines
/* Copyright (C) 1989, 1992, 1993, 1994 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
or distributor accepts any responsibility for the consequences of using it,
or for whether it serves any particular purpose or works at all, unless he
or she says so in writing. Refer to the Aladdin Ghostscript Free Public
License (the "License") for full details.
Every copy of Aladdin Ghostscript must include a copy of the License,
normally in a plain ASCII text file named PUBLIC. The License grants you
the right to copy, modify and redistribute Aladdin Ghostscript, but only
under certain conditions described in the License. Among other things, the
License requires that the copyright notice and this notice be preserved on
all copies.
*/
/* gp_amiga.c */
/* Amiga-specific routines for Ghostscript */
#include <dos/dosextens.h>
#include <graphics/gfxbase.h>
#include <intuition/intuitionbase.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include "dirent_.h"
#include "stat_.h"
#include "string_.h"
#include "time_.h"
#include "gx.h"
#include "gp.h"
#include "gsexit.h"
#include "gsstruct.h"
#include "gsutil.h"
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/param.h> /* for MAXPATHLEN */
#if defined(mc68020)
#ifdef __HAVE_68881__
STATIC STRPTR VersTag = "$VER: gs 5.01 (22.06.97) MC68020/FPU version\r\n";
#else
STATIC STRPTR VersTag = "$VER: gs 5.01 (22.06.97) MC68020 version\r\n";
#endif /* __HAVE_68881__ */
#elif defined(mc68030)
#ifdef __HAVE_68881__
STATIC STRPTR VersTag = "$VER: gs 5.01 (22.06.97) MC68030/FPU version\r\n";
#else
STATIC STRPTR VersTag = "$VER: gs 5.01 (22.06.97) MC68030 version\r\n";
#endif /* __HAVE_68881__ */
#elif defined(mc68040)
#ifdef __HAVE_68881__
STATIC STRPTR VersTag = "$VER: gs 5.01 (22.06.97) MC68040/FPU version\r\n";
#else
STATIC STRPTR VersTag = "$VER: gs 5.01 (22.06.97) MC68040 version\r\n";
#endif /* __HAVE_68881__ */
#elif defined(mc68060)
#ifdef __HAVE_68881__
STATIC STRPTR VersTag = "$VER: gs 5.01 (22.06.97) MC68060/FPU version\r\n";
#else
STATIC STRPTR VersTag = "$VER: gs 5.01 (22.06.97) MC68060 version\r\n";
#endif /* __HAVE_68881__ */
#else
STATIC STRPTR VersTag = "$VER: gs 5.01 (22.06.97)\r\n";
#endif /* mc68020 */
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Library *LayersBase,
*IFFParseBase,
*AslBase,
*UtilityBase;
/*struct DosLibrary *DOSBase;
struct MathIEEEBase *MathIeeeDoubBasBase;*/
/* Cleanup routine, as called by atexit() trap */
void
cleanup(void)
{
extern void devcleanup(void);
devcleanup();
if(IFFParseBase)
{
CloseLibrary(IFFParseBase);
IFFParseBase = NULL;
}
if(AslBase)
{
CloseLibrary(AslBase);
AslBase = NULL;
}
if(UtilityBase)
{
CloseLibrary(UtilityBase);
UtilityBase = NULL;
}
if(LayersBase)
{
CloseLibrary(LayersBase);
LayersBase = NULL;
}
if(GfxBase)
{
CloseLibrary((struct Library *)GfxBase);
GfxBase = NULL;
}
if(IntuitionBase)
{
CloseLibrary((struct Library *)IntuitionBase);
IntuitionBase = NULL;
}
}
void
signal_handler(int signal)
{
fprintf(stderr,"*** BREAK: Ghostscript\a\n");
gs_exit(1);
}
/* Do platform-dependent initialization. */
void
gp_init(void)
{
atexit(cleanup);
signal(SIGINT,signal_handler);
if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37)))
{
eprintf("Ghostscript: cannot open intuition.library v37\n");
exit(20);
}
if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",37)))
{
eprintf("Ghostscript: cannot open graphics.library v37\n");
exit(20);
}
if(!(LayersBase = OpenLibrary("layers.library",37)))
{
eprintf("Ghostscript: cannot open layers.library v37\n");
exit(20);
}
if(!(UtilityBase = OpenLibrary("utility.library",37)))
{
eprintf("Ghostscript: cannot open utility.library v37\n");
exit(20);
}
if(!(IFFParseBase = OpenLibrary("iffparse.library",37)))
{
eprintf("Ghostscript: cannot open iffparse.library v37\n");
exit(20);
}
AslBase = OpenLibrary("asl.library",38);
}
/* Do platform-dependent cleanup. */
void
gp_exit(int exit_status, int code)
{
cleanup();
}
/* Exit the program. */
void
gp_do_exit(int exit_status)
{ exit(exit_status);
}
/* ------ Miscellaneous ------ */
/*
* Get the string corresponding to an OS error number.
* If no string is available, return NULL. The caller may assume
* the string is allocated statically and permanently.
*/
const char *
gp_strerror(int errnum)
{ return (strerror(errnum));
}
/* ------ Date and time ------ */
/* Read the current time (in seconds since Jan. 1, 1970) */
/* and fraction (in nanoseconds). */
void
gp_get_realtime(long *pdt)
{
#if defined(IXEMUL)
struct timeval tp;
#if gettimeofday_no_timezone /* older versions of SVR4 */
{ if ( gettimeofday(&tp) == -1 )
{ lprintf("Ghostscript: gettimeofday failed!\n");
gs_exit(1);
}
}
#else /* All other systems */
{ struct timezone tzp;
if ( gettimeofday(&tp, &tzp) == -1 )
{ lprintf("Ghostscript: gettimeofday failed!\n");
gs_exit(1);
}
}
#endif
/* tp.tv_sec is #secs since Jan 1, 1970 */
pdt[0] = tp.tv_sec;
/* Some Unix systems (e.g., Interactive 3.2 r3.0) return garbage */
/* in tp.tv_usec. Try to filter out the worst of it here. */
pdt[1] = tp.tv_usec >= 0 && tp.tv_usec < 1000000 ? tp.tv_usec*1000 : 0;
#else
LONG secs, micros;
CurrentTime(&secs, µs);
pdt[0] = secs;
pdt[1] = micros*1000;
#endif
#ifdef DEBUG_CLOCK
printf("tp.tv_sec = %d tp.tv_usec = %d pdt[0] = %ld pdt[1] = %ld\n",
tp.tv_sec, tp.tv_usec, pdt[0], pdt[1]);
#endif
}
/* Read the current user CPU time (in seconds) */
/* and fraction (in nanoseconds). */
void
gp_get_usertime(long *pdt)
{
#if use_times_for_usertime
LONG secs, micros;
CurrentTime(&secs, µs);
pdt[0] = secs;
pdt[1] = micros*1000;
#else
gp_get_realtime(pdt); /* Use an approximation on other hosts. */
#endif
}
/* ------ Screen management ------ */
/* Get the environment variable that specifies the display to use. */
const char *
gp_getenv_display(void)
{ return getenv("DISPLAY");
}
/* ------ Printer accessing ------ */
/* Open a connection to a printer. A null file name means use the */
/* standard printer connected to the machine, if any. */
/* "|command" opens an output pipe. */
/* Return NULL if the connection could not be opened. */
FILE *
gp_open_printer(char *fname, int binary_mode)
{
#ifndef IXEMUL
return
(strlen(fname) == 0 ?
gp_open_scratch_file(gp_scratch_file_name_prefix, fname, "w") :
fname[0] == '|' ?
NULL :
fopen(fname, "w"));
#else
return
(strlen(fname) == 0 ?
gp_open_scratch_file(gp_scratch_file_name_prefix, fname, "w") :
fname[0] == '|' ?
popen(fname + 1, "w") :
fopen(fname, "w"));
#endif
}
/* Close the connection to the printer. */
void
gp_close_printer(FILE *pfile, const char *fname)
{
#ifndef IXEMUL
fclose(pfile);
#else
if ( fname[0] == '|' )
pclose(pfile);
else
fclose(pfile);
#endif
}
/* ------ File name syntax ------ */
/* Define the character used for separating file names in a list. */
const char gp_file_name_list_separator = ',';
/* Define the string to be concatenated with the file mode */
/* for opening files without end-of-line conversion. */
const char gp_fmode_binary_suffix[] = "";
/* Define the file modes for binary reading or writing. */
const char gp_fmode_rb[] = "r";
const char gp_fmode_wb[] = "w";
/* Answer whether a file name contains a directory/device specification, */
/* i.e. is absolute (not directory- or device-relative). */
int
gp_file_name_is_absolute(const char *fname, uint len)
{
int i;
for(i = 0 ; i < len ; i++)
{
if(fname[i] == ':')
return(1);
}
return(0);
}
/* Answer the string to be used for combining a directory/device prefix */
/* with a base file name. The file name is known to not be absolute. */
const char *
gp_file_name_concat_string(const char *prefix, uint plen, const char *fname, uint len)
{
#ifdef IXEMUL
if(plen > 0 && (prefix[plen - 1] == '/' || prefix[plen - 1] == ':'))
return("");
else
return("/");
#else
if(plen > 0)
if(prefix[plen - 1] == '/' || prefix[plen - 1] == ':')
return("");
else
return("/");
else
return("");
#endif
}
/* ------ File naming and accessing ------ */
/* Define the default scratch file name prefix. */
const char gp_scratch_file_name_prefix[] = "T:gs_";
/* Define the name of the null output file. */
#ifdef IXEMUL
const char gp_null_file_name[] = "/dev/null";
#else
const char gp_null_file_name[] = "NIL:";
#endif
/* Define the name that designates the current directory. */
#ifdef IXEMUL
const char gp_current_directory_name[] = ".";
#else
const char gp_current_directory_name[] = "";
#endif
/* Create and open a scratch file with a given name prefix. */
/* Write the actual file name at fname. */
FILE *
gp_open_scratch_file(const char *prefix, char *fname, const char *mode)
{
#ifndef IXEMUL
char *temp;
char temp2[100];
struct Task *thistask;
LONG secs, micros;
#endif
strcpy(fname,prefix);
/* Prevent trailing X's in path from being converted by mktemp. */
if ( *fname != 0 && fname[strlen(fname) - 1] == 'X' )
strcat(fname, "-");
#ifdef IXEMUL
strcat(fname, "XXXXXX");
#else
CurrentTime(&secs, µs);
sprintf(temp2,"%08lx_%08lx_%08lx",FindTask(NULL), secs, micros);
/* this looks stupid but a reasonable chance exists that you end up with the
same time if scratch files are opened fast enough
*/
Delay(3);
strcat(fname, temp2);
#endif
#ifdef IXEMUL
mktemp(fname);
#endif
return fopen(fname, mode);
}
/* Open a file with the given name, as a stream of uninterpreted bytes. */
FILE *
gp_fopen(const char *fname, const char *mode)
{ return fopen(fname, mode);
}
/* ------ File enumeration ------ */
/* Thanks to Fritz Elfert (Fritz_Elfert@wue.maus.de) for */
/* the original version of the following code, and Richard Mlynarik */
/* (mly@adoc.xerox.com) for an improved version. */
typedef struct dirstack_s dirstack;
struct dirstack_s {
dirstack *next;
DIR *entry;
};
gs_private_st_ptrs1(st_dirstack, dirstack, "dirstack",
dirstack_enum_ptrs, dirstack_reloc_ptrs, next);
struct file_enum_s {
DIR *dirp; /* pointer to current open directory */
char *pattern; /* original pattern */
char *work; /* current path */
int worklen; /* strlen (work) */
dirstack *dstack; /* directory stack */
int patlen;
int pathead; /* how much of pattern to consider
* when listing files in current directory */
bool first_time;
gs_memory_t *memory;
};
gs_private_st_ptrs3(st_file_enum, struct file_enum_s, "file_enum",
file_enum_enum_ptrs, file_enum_reloc_ptrs, pattern, work, dstack);
/* Private procedures */
/* Do a wild-card match. */
#ifdef DEBUG
private bool
wmatch(const byte *str, uint len, const byte *pstr, uint plen,
const string_match_params *psmp)
{ bool match = string_match(str, len, pstr, plen, psmp);
if ( gs_debug_c('e') )
{ dputs("[e]string_match(\"");
fwrite(str, 1, len, dstderr);
dputs("\", \"");
fwrite(pstr, 1, plen, dstderr);
dprintf1("\") = %s\n", (match ? "TRUE" : "false"));
}
return match;
}
#define string_match wmatch
#endif
/* Search a string backward for a character. */
/* (This substitutes for strrchr, which some systems don't provide.) */
private char *
rchr(char *str, char ch, int len)
{ register char *p = str + len;
while ( p > str )
if ( *--p == ch ) return p;
return 0;
}
/* Pop a directory from the enumeration stack. */
private bool
popdir(file_enum *pfen)
{ dirstack *d = pfen->dstack;
if ( d == 0 )
return false;
pfen->dirp = d->entry;
pfen->dstack = d->next;
gs_free_object(pfen->memory, d, "gp_enumerate_files(popdir)");
return true;
}
/* Initialize an enumeration. */
file_enum *
gp_enumerate_files_init(const char *pat, uint patlen, gs_memory_t *mem)
{ file_enum *pfen;
char *p;
char *work;
/* Reject attempts to enumerate paths longer than the */
/* system-dependent limit. */
if ( patlen > MAXPATHLEN )
return 0;
/* Reject attempts to enumerate with a pattern containing zeroes. */
{ const char *p1;
for (p1 = pat; p1 < pat + patlen; p1++)
if (*p1 == 0) return 0;
}
/* >>> Should crunch strings of repeated "/"'s in pat to a single "/"
* >>> to match stupid unix filesystem "conventions" */
pfen = gs_alloc_struct(mem, file_enum, &st_file_enum,
"gp_enumerate_files");
if (pfen == 0)
return 0;
/* pattern and work could be allocated as strings, */
/* but it's simpler for GC and freeing to allocate them as bytes. */
pfen->pattern =
(char *)gs_alloc_bytes(mem, patlen + 1,
"gp_enumerate_files(pattern)");
if (pfen->pattern == 0)
return 0;
memcpy(pfen->pattern, pat, patlen);
pfen->pattern[patlen] = 0;
work = (char *)gs_alloc_bytes(mem, MAXPATHLEN+1,
"gp_enumerate_files(work)");
if (work == 0)
return 0;
pfen->work = work;
p = work;
memcpy(p, pat, patlen);
p += patlen;
*p = 0;
/* Remove directory specifications beyond the first wild card. */
/* Some systems don't have strpbrk, so we code it open. */
p = pfen->work;
while ( !(*p == '*' || *p == '?' || *p == 0) ) p++;
while ( !(*p == '/' || *p == 0) ) p++;
if ( *p == '/' )
*p = 0;
/* Substring for first wildcard match */
pfen->pathead = p - work;
/* Select the next higher directory-level. */
p = rchr(work, '/', p - work);
if (!p)
{ /* No directory specification */
work[0] = 0;
pfen->worklen = 0;
}
else
{ if (p == work)
{ /* Root directory -- don't turn "/" into "" */
p++;
}
*p = 0;
pfen->worklen = p - work;
}
pfen->memory = mem;
pfen->dstack = 0;
pfen->first_time = true;
pfen->patlen = patlen;
return pfen;
}
/* Enumerate the next file. */
uint
gp_enumerate_files_next(file_enum *pfen, char *ptr, uint maxlen)
{ dir_entry *de;
char *work = pfen->work;
int worklen = pfen->worklen;
char *pattern = pfen->pattern;
int pathead = pfen->pathead;
int len;
struct stat stbuf;
if ( pfen->first_time )
{ pfen->dirp = ((worklen == 0) ? opendir(".") : opendir(work));
if_debug1('e', "[e]file_enum:First-Open '%s'\n", work);
pfen->first_time = false;
if (pfen->dirp == 0) /* first opendir failed */
{ gp_enumerate_files_close(pfen);
return ~(uint)0;
}
}
top: de = readdir(pfen->dirp);
if (de == 0)
{ /* No more entries in this directory */
char *p;
if_debug0('e', "[e]file_enum:Closedir\n");
closedir(pfen->dirp);
/* Back working directory and matching pattern up one level */
p = rchr(work,'/', worklen);
if (p != 0)
{ if (p == work) p++;
*p = 0;
worklen = p - work;
}
else
worklen = 0;
p = rchr(pattern,'/', pathead);
if (p != 0)
pathead = p - pattern;
else
pathead = 0;
if (popdir(pfen))
{ /* Back up the directory tree. */
if_debug1('e', "[e]file_enum:Dir popped '%s'\n", work);
goto top;
}
else
{ if_debug0('e', "[e]file_enum:Dirstack empty\n");
gp_enumerate_files_close(pfen);
return ~(uint)0;
}
}
/* Skip . and .. */
len = strlen(de->d_name);
if (len <= 2 && (!strcmp(de->d_name,".") || !strcmp(de->d_name,"..") ))
goto top;
if (len + worklen + 1 > MAXPATHLEN)
/* Should be an error, I suppose */
goto top;
if (worklen == 0)
{ /* "Current" directory (evil un*x kludge) */
memcpy(work, de->d_name, len + 1);
}
else if (worklen == 1 && work[0] == '/')
{ /* Root directory */
memcpy(work + 1, de->d_name, len + 1);
len = len + 1;
}
else
{ work[worklen] = '/';
memcpy(work + worklen + 1, de->d_name, len + 1);
len = worklen + 1 + len;
}
/* Test for a match at this directory level */
if (!string_match((byte *)work, len, (byte *)pattern, pathead, NULL))
goto top;
/* Perhaps descend into subdirectories */
if (pathead < pfen->patlen)
{ DIR *dp;
if (((stat(work,&stbuf) >= 0)
? !stat_is_dir(stbuf)
/* Couldn't stat it.
* Well, perhaps it's a directory and
* we'll be able to list it anyway.
* If it isn't or we can't, no harm done. */
: 0))
goto top;
if (pfen->patlen == pathead + 1)
{ /* Listing "foo/?/" -- return this entry */
/* if it's a directory. */
if (!stat_is_dir (stbuf))
{ /* Do directoryp test the hard way */
dp = opendir(work);
if (!dp) goto top;
closedir(dp);
}
work[len++] = '/';
goto winner;
}
/* >>> Should optimise the case in which the next level */
/* >>> of directory has no wildcards. */
dp = opendir(work);
#ifdef DEBUG
{ char save_end = pattern[pathead];
pattern[pathead] = 0;
if_debug2('e', "[e]file_enum:fname='%s', p='%s'\n",
work, pattern);
pattern[pathead] = save_end;
}
#endif /* DEBUG */
if (!dp)
/* Can't list this one */
goto top;
else
{ /* Advance to the next directory-delimiter */
/* in pattern */
char *p;
dirstack *d;
for (p = pattern + pathead + 1; ; p++)
{ if (*p == 0)
{ /* No more subdirectories to match */
pathead = pfen->patlen;
break;
}
else if (*p == '/')
{ pathead = p - pattern;
break;
}
}
/* Push a directory onto the enumeration stack. */
d = gs_alloc_struct(pfen->memory, dirstack,
&st_dirstack,
"gp_enumerate_files(pushdir)");
if ( d != 0 )
{
d->next = pfen->dstack;
d->entry = pfen->dirp;
pfen->dstack = d;
}
else
DO_NOTHING; /* >>> e_VMerror!!! */
if_debug1('e', "[e]file_enum:Dir pushed '%s'\n",
work);
worklen = len;
pfen->dirp = dp;
goto top;
}
}
winner:
/* We have a winner! */
pfen->worklen = worklen;
pfen->pathead = pathead;
memcpy(ptr, work, len);
return len;
}
/* Clean up the file enumeration. */
void
gp_enumerate_files_close(file_enum *pfen)
{ gs_memory_t *mem = pfen->memory;
if_debug0('e', "[e]file_enum:Cleanup\n");
while (popdir(pfen)) /* clear directory stack */
DO_NOTHING;
gs_free_object(mem, (byte *)pfen->work,
"gp_enumerate_close(work)");
gs_free_object(mem, (byte *)pfen->pattern,
"gp_enumerate_files_close(pattern)");
gs_free_object(mem, pfen, "gp_enumerate_files_close");
}
/***************************************************************************/
/* Functions from ixemul.library source which aren't in Libnix */
/***************************************************************************/
#ifndef IXEMUL
/***************************************************************************/
/* modf.c */
/***************************************************************************/
#include <proto/mathieeedoubbas.h>
/*
* modf(value, iptr): return fractional part of value, and stores the
* integral part into iptr (a pointer to double).
*/
double
modf (double value, double *iptr)
{
/* if value negative */
if (IEEEDPTst (value) < 0)
{
/* in that case, the integer part is calculated by ceil() */
*iptr = IEEEDPCeil (value);
return IEEEDPSub (*iptr, value);
}
else
{
/* if positive, we go for the floor() */
*iptr = IEEEDPFloor (value);
return IEEEDPSub (value, *iptr);
}
}
/***************************************************************************/
/* frexp.c */
/***************************************************************************/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)frexp.c 5.2 (Berkeley) 3/9/86";
#endif LIBC_SCCS and not lint
#define KERNEL
/*#include "ixemul.h"*/
/*
* the call
* x = frexp(arg,&exp);
* must return a double fp quantity x which is <1.0
* and the corresponding binary exponent "exp".
* such that
* arg = x*2^exp
* if the argument is 0.0, return 0.0 mantissa and 0 exponent.
*/
double
frexp(double x, int *i)
{
int neg;
int j;
j = 0;
neg = 0;
if (x < 0)
{
x = -x;
neg = 1;
}
if (x >= 1.0)
while(x >= 1.0)
{
j = j+1;
x = x/2;
}
else if(x < 0.5 && x != 0.0)
while(x < 0.5)
{
j = j-1;
x = 2*x;
}
*i = j;
if (neg) x = -x;
return x;
}
/***************************************************************************/
/* ldexp.c */
/***************************************************************************/
/*
* ldexp returns the quanity "value" * 2 ^ "exp"
*
* For the mc68000 using IEEE format the double precision word format is:
*
* WORD N => SEEEEEEEEEEEMMMM
* WORD N+1 => MMMMMMMMMMMMMMMM
* WORD N+2 => MMMMMMMMMMMMMMMM
* WORD N+3 => MMMMMMMMMMMMMMMM
*
* Where: S => Sign bit
* E => Exponent
* X => Ignored (set to 0)
* M => Mantissa bit
*
* NOTE: Beware of 0.0; on some machines which use excess 128 notation for the
* exponent, if the mantissa is zero the exponent is also.
*
*/
#define MANT_MASK 0x800FFFFF /* Mantissa extraction mask */
#define ZPOS_MASK 0x3FF00000 /* Positive # mask for exp = 0 */
#define ZNEG_MASK 0x3FF00000 /* Negative # mask for exp = 0 */
#define EXP_MASK 0x7FF00000 /* Mask for exponent */
#define EXP_SHIFTS 20 /* Shifts to get into LSB's */
#define EXP_BIAS 1023 /* Exponent bias */
union dtol
{
double dval;
int ival[2];
};
double
ldexp (value, exp)
double value;
int exp;
{
union dtol number;
int *iptr, cexp;
if (value == 0.0)
return (0.0);
else
{
number.dval = value;
iptr = &number.ival[0];
cexp = (((*iptr) & EXP_MASK) >> EXP_SHIFTS) - EXP_BIAS;
*iptr &= ~EXP_MASK;
exp += EXP_BIAS;
*iptr |= ((exp + cexp) << EXP_SHIFTS) & EXP_MASK;
return (number.dval);
}
}
#endif